﻿using Microsoft.AspNetCore.Hosting;

namespace Digitalmes.Application.Sys;

/// <summary>
/// 系统文件服务
/// </summary>
[NoApiSecurity]
[ApiExplorerSettings(GroupName = "sys")]
public sealed class SysFileService : IDynamicWebApiService
{
    private readonly SysSafetyService _safetyService;
    private readonly IHttpContextAccessor _httpContextAccessor;
    private readonly IWebHostEnvironment _webHostEnvironment;

    public SysFileService(SysSafetyService safetyService, 
        IHttpContextAccessor httpContextAccessor, 
        IWebHostEnvironment webHostEnvironment)
    {
        _safetyService = safetyService;
        _httpContextAccessor = httpContextAccessor;
        _webHostEnvironment = webHostEnvironment;
    }

    /// <summary>
    /// 查询目录-树形结构
    /// </summary>
    /// <param name="path"></param>
    /// <returns></returns>
    public List<FileFolder> GetDirectory(string path)
    {
        if (string.IsNullOrEmpty(path))
        {
            path = Path.Combine(_webHostEnvironment.WebRootPath, "upload");
        }

        return FileUtils.GetFileDirectory(path);
    }

    /// <summary>
    /// 根据目录查询文件
    /// </summary>
    /// <param name="path"></param>
    /// <returns></returns>
    public List<TreeFile> GetList(string path)
    {
        if (string.IsNullOrEmpty(path))
        {
            path = Path.Combine(_webHostEnvironment.WebRootPath, "upload");
        }
        return FileUtils.GetDirAllFiles(path);
    }

    /// <summary>
    /// 根据目录查询文件
    /// </summary>
    /// <returns></returns>
    public List<FileContentInfo> GetFiles(string path, string filetype)
    {
        var basePath = _webHostEnvironment.WebRootPath;
        var path0 = Path.Combine(basePath, string.IsNullOrEmpty(path) ? "upload" : path);

        return FileUtils.ResolveFileInfo(path0, filetype, basePath);
    }

    /// <summary>
    /// 上传文件
    /// </summary>
    /// <returns></returns>
    public async Task<SysFileDto> Uploading([FromForm] IFormFile file, string path)
    {
        if (file == null)
        {
            throw Oops.Bah("请上传文件~");
        }

        var safety = _safetyService.Get();
        //原文件名
        var filename = file.FileName;
        //扩展名
        var fileExt = FileUtils.GetFileExt(filename);
        if (!string.IsNullOrEmpty(safety?.UploadWhite))
        {
            var arr = safety.UploadWhite.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
            if (!arr.Contains(fileExt))
            {
                throw Oops.Bah("文件类型不存在【上传白名单】中，不允许上传~");
            }
        }

        var basePath = Path.Combine(_webHostEnvironment.WebRootPath, path);
        FileUtils.CreateDirectoryIfNotExists(basePath);
        var filePath = Path.Combine(basePath, filename);
        await using (var stream = new FileStream(filePath, FileMode.Create))
        {
            await file.CopyToAsync(stream);
            stream.Flush();
        }

        return new SysFileDto()
        {
            path = path + filename,
            name = filename,
            size = Convert.ToInt64(Math.Round(Convert.ToDecimal(file.Length / 1024), 0))
        };
    }

    /// <summary>
    /// 上传文件
    /// </summary>
    /// <returns></returns>
    public async Task<SysFileDto> Upload(string path)
    {
        var httpFile = (_httpContextAccessor.HttpContext?.Request.Form.Files[0]) ?? throw new ArgumentException("上传文件不能为空~");

        var safety = _safetyService.Get();
        //原文件名
        var filename = httpFile.FileName;
        var fileExt = FileUtils.GetFileExt(filename);
        if (!string.IsNullOrEmpty(safety?.UploadWhite))
        {
            var arr = safety.UploadWhite.Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
            if (!arr.Contains(fileExt))
            {
                throw Oops.Bah("文件类型不存在【上传白名单】中，不允许上传~");
            }
        }

        filename = $"{TimeUtils.GetTimeStamp2()}.{fileExt}";
        var basePath = Path.Combine(_webHostEnvironment.WebRootPath, path);
        FileUtils.CreateDirectoryIfNotExists(basePath);
        var filePath = Path.Combine(basePath, filename);
        await using (var stream = new FileStream(filePath, FileMode.Create))
        {
            await httpFile.CopyToAsync(stream);
            stream.Flush();
        }

        return new SysFileDto()
        {
            path = path + filename,
            name = filename,
            size = Convert.ToInt64(Math.Round(Convert.ToDecimal(httpFile.Length / 1024), 0))
        };
    }

    /// <summary>
    /// 删除文件
    /// </summary>
    /// <returns></returns>
    public void DeleteFile(string path)
    {
        var basePath = Path.Combine(_webHostEnvironment.WebRootPath, path);
        FileUtils.DeleteFileIfExists(basePath);
    }

    /// <summary>
    /// 删除目录及目录下文件
    /// </summary>
    /// <returns></returns>
    public void DeleteDirectory(string path)
    {
        var basePath = Path.Combine(_webHostEnvironment.WebRootPath, path);
        FileUtils.ClearDirectory(basePath);
        FileUtils.DeleteDirectoryIfExists(basePath);
    }
}
